package com.course.domain.service.impl;

import com.course.domain.dao.CoursePlanDao;
import com.course.domain.dao.LearnRecordDao;
import com.course.domain.dao.LearnStatDao;
import com.course.domain.dao.TaskGroupDao;
import com.course.domain.enums.TaskType;
import com.course.domain.model.CoursePlan;
import com.course.domain.model.LearnRecord;
import com.course.domain.model.LearnStat;
import com.course.domain.model.TaskGroup;
import com.course.domain.service.LearnService;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.List;

/**
 * Created by Justin on 2017/7/1.
 */
@Service
public class LearnServiceImpl implements LearnService {

    private final CoursePlanDao coursePlanDao;
    private final LearnRecordDao recordDao;
    private final LearnStatDao statDao;
    private final TaskGroupDao groupDao;

    @Autowired
    public LearnServiceImpl(CoursePlanDao coursePlanDao,
                            LearnRecordDao recordDao,
                            LearnStatDao statDao,
                            TaskGroupDao groupDao) {
        this.coursePlanDao = coursePlanDao;
        this.recordDao = recordDao;
        this.statDao = statDao;
        this.groupDao = groupDao;
    }

    @Override
    public List<LearnStat> findStat(int courseId, int weekIdx, int weekDay) {
        return statDao.findByCourseIdAndWeekIdxAndWeekDay(courseId, weekIdx, weekDay);
    }

    @Override
    public LearnStat loadStat(int studentId, int courseId, int weekIdx, int weekDay) {
        LearnStat stat = statDao.findByStudentIdAndCourseIdAndWeekIdxAndWeekDay(studentId, courseId, weekIdx, weekDay);
        if (stat == null) {
            stat = buildStat(studentId, courseId, weekIdx, weekDay);
        }
        return stat;
    }

    @Transactional
    @Override
    public boolean doneRecord(int studentId, int courseId, int groupId) {
        TaskGroup group = groupDao.findOne(groupId);
        if (group == null || group.getCourseId() != courseId) {
            return false;
        }
        int taskId = group.getTaskId();
        CoursePlan plan = coursePlanDao.findByCourseIdAndTaskIdAndTaskType(courseId, taskId, TaskType.LEARN);
        if (plan == null) {
            return false;
        }
        int weekIdx = plan.getWeekIdx();
        int weekDay = plan.getWeekDay();
        LearnStat stat = statDao.findByStudentIdAndCourseIdAndWeekIdxAndWeekDay(studentId, courseId, weekIdx, weekDay);
        if (stat == null) {
            stat = buildStat(studentId, courseId, weekIdx, weekDay);
            statDao.save(stat);
        }

        LearnRecord record = new LearnRecord();
        record.setStudentId(studentId);
        record.setCourseId(courseId);
        record.setGroupId(groupId);
        record.setStatus(1);
        try {
            recordDao.save(record);
            if (statDao.done(studentId, courseId, weekIdx, weekDay) == 1) {
                return true;
            } else {
                throw new RuntimeException();
            }
        } catch (Exception e) {
            return false;
        }
    }

    private LearnStat buildStat(int studentId, int courseId, int weekIdx, int weekDay) {
        List<CoursePlan> plans = coursePlanDao.findByCourseIdAndWeekIdxAndWeekDay(courseId, weekIdx, weekDay);
        List<Integer> taskIds = Lists.transform(plans, CoursePlan::getTaskId);
        int total = groupDao.countByTaskIdIn(taskIds);
        LearnStat stat = new LearnStat();
        stat.setStudentId(studentId);
        stat.setCourseId(courseId);
        stat.setWeekIdx(weekIdx);
        stat.setWeekDay(weekDay);
        stat.setTotal(total);
        stat.setDone(0);
        stat.setStatus(1);
        return stat;
    }
}
